Coercion (型別轉換)其實最令人煩惱的不是 一元運算子的 + 或是 加法運算子的 多載問題。
其實最多人一開始採的坑是 Equality (相等) 問題。

以下是最常見的描述:
兩個 == 一般相等 比較 值。三個 === 是嚴格相等,比較 值 和 型別。但很抱歉,這樣寫都是錯的。
這邊是 Spec.
第一行
== 一般相等 等效 === 嚴格相等
也就是說,如果你了解 code 裡面寫的型別都一樣,可以放心用 == 一般相等


如果型別不同,直接回傳 False
(也就是連值都 不會比較)
先比較數字型別的狀況
(a.) (b.) 實作 IEEE 754 定義 (NaN ≠ x) = false.
之前有寫過 NaN,參考
[day06] YDKJS (Type) : 特殊值:undefined / undeclared / TDZ ? , NaN , 負數 0
值 相等就回傳 true之前有寫過 負數 0,參考
[[day06] YDKJS (Type) : 特殊值:undefined / undeclared / TDZ ? , NaN , 負數 0]
嚴格相等( === )大家從小就會,補充閱讀 Spec.
Null , undefined可以繼續比較一定同型別,且該型別只有一個值,當然會相等string要相同的長度和相同的字元對應相同的位置才會回傳 trueBoolean只有兩個值,比對是否相等很容易SymbolSymbol value 一樣才會回傳 trueObject太多問題,不建議做比對。(自己挖掘 Spec. 這邊不深入)
== 允許在等價性比較中進行強制轉換,而 === 不允許強制轉換。
一般相等(==) ,因為它不可預測 ?一個簡單的問題,如果不能預測,那 JavaScript 語言要怎麼實作?
量子 JavaScript ? 沒觀察就處於疊加態 ? ( 老高看太多 XDDD )
不如這樣說,
先學會,再來考慮要不要使用。這一直是這個系列主題的宗旨:打造全新 JavaScript Mindset ,而不是一律使用 嚴格相等(===) 就不用學。
順帶一提,
如果你只使用 嚴格相等(===) ,沒認真思考過你寫的 code 其值與型別,
那麼得到 false,你會不知道其實這邊得到的 false 有兩個意涵:
型別不一樣。型別一樣,但其Equality comparison 失敗。所以,還是認真學習 一般相等(==) a.k.a. 抽象等價性 (之前說過型別轉換可以視為隱藏細節的抽象),把目光放在 「抽象等價性」的 Equality comparison。
「之前」參考以下文章
[day10] YDKJS (Coercion) : 如何決定何時使用「顯性」或是「隱性」的型別轉換?
一般相等 Spec. Abstract Equality Comparison 7.2.14
line 2, 3
JavaScript 在 抽象等價性 的比對上, null , undefined 把兩者視為相等。
有時候可能你會用 null , 有些人可能用 undefined 。
或是你只是單純想知道,是不是設定清除賦值的 undefined, null 狀態。
在某些時候,這兩個值他們會不一樣,但至少做 比對(==) 時視為相等,不用去思考那個很複雜的 ToPrimitive()。
參考以下例子
你可以用抽象等價性 來查看一個屬性的「值」是不是 設定為空或是沒有初始值,
如果你用 嚴格相等 ,你要把所有的狀況都寫上去,因為 null 和 undefined 型別不同。
如果你用 抽象等價性 ,可以把你的 code 寫比較簡潔。
(用 null 而不使用 undefined 只是純粹因為字可以打比較少 XDDDD )
ESLine 好像會提示,Kyle Simpson 有調整這一個 rule,best tools are the ones that are most configurable
之前有寫過
undefined 典型用法是:
1 .變數被宣告了,但沒有賦值時,就等於 undefined。
2. 呼叫函式時,應該提供的引數沒有提供,該引數等於 undefined。3. 物件沒有沒有賦值的屬性,該屬性的值為 undefined。
4. 函式沒有回傳值時,預設回傳 undefined。
[day05] YDKJS (Type) : 初學者第一坑 - typeof 運算子, 詳解 undefined
line 4 ~ 7
ToNumber()string => ToNumber() 之後做數字相等運算 (numeric comparison)boolean => ToNumber() 之後做比對 ! ToNumber(x) == y. 或是 x == ! ToNumber(y).
再複習一下 ToNumber()
- 空字串變成
0![]()
- false -> 0 , true -> 1
reference:
[day08] YDKJS (Coercion:spec) : 回來讀 spec. ToString(), ToNumber() , ToBoolean()
參考以下例子
我自己經驗是,有時候 element.value 可能是字面值的數字(type 還是 string: "1"),
但是如果要做比較還要做型別轉換 (比如 + 一元運算子 會做 ToNumber() )。
其實在這個例子中,不用像是 line 4 做轉換,可以放心使用 抽象等價性 ( == )
line 8,line 9 : top level objects type 都會做 ToPrimitive()
抽象等價性依然做偏好數字的運算。註:不要忘記兩邊都是 object -> 型別一樣就是演算法第一行,執行 === 嚴格相等
Primitive value:
不要忘記, ToPrimitive() 是第一個講的 abstract operations
reference
[day07] YDKJS (Type/Coercion) : Type總結 和 abstract operations (Spec.)
抽象等價性 ( == )因為只會給你自己帶來麻煩。
範例如下:
拆解步驟:
line 5 : 先 ToPrimitive()
line 6 : 抽象等價性 偏好ToNumber()=> 轉成數字。
順帶一提,拿 array 和 數字 做比較,程式可以寫得出來(因為電腦可以讀,不會報錯),
但這樣寫的背後意義不符合邏輯,沒有任何原因出現這樣的 code。
如果有,請仔細思考情境,最好適度重構。
而不是使用 嚴格相等 === 來逃避重構這些不合邏輯且沒有意義的 code。
從邏輯上也應該只有 Primitive 會做比對。
無論任何時候,避免對 non-Primitive 做「任何比對」。
一個會有 non-Primitive 可以做 抽象等價性 ( == ) 的歷史原因,
是因為很早期習慣用 new 關鍵字產生 string , number 。
這些透過 new 產生的結果要 ToPrimitive() 才做 抽象等價性 ( == ) 。
但是這個用法已經非常不建議使用,所以不會有這個情境了。

明天的文章會延續今天主題,以 Corner Cases 整理,或是說練習為主。